/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * N.Metchev@teamphone.com - contributed fixes for * - convert anonymous to nested should sometimes declare class as static [refactoring] * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=43360) * - Convert anonymous to nested: should show error if field form outer anonymous type is references [refactoring] * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=48282) *******************************************************************************/ package org.eclipse.jdt.internal.corext.refactoring.code; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.Refactoring; import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor; import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.NamingConventions; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; import org.eclipse.jdt.core.dom.ArrayCreation; import org.eclipse.jdt.core.dom.ArrayInitializer; import org.eclipse.jdt.core.dom.ArrayType; import org.eclipse.jdt.core.dom.Assignment; import org.eclipse.jdt.core.dom.BodyDeclaration; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.FieldAccess; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.Initializer; import org.eclipse.jdt.core.dom.Javadoc; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.NodeFinder; import org.eclipse.jdt.core.dom.ParameterizedType; import org.eclipse.jdt.core.dom.QualifiedName; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.Statement; import org.eclipse.jdt.core.dom.SuperConstructorInvocation; import org.eclipse.jdt.core.dom.SuperFieldAccess; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.TypeParameter; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; import org.eclipse.jdt.core.refactoring.CompilationUnitChange; import org.eclipse.jdt.core.refactoring.IJavaRefactorings; import org.eclipse.jdt.core.refactoring.descriptors.ConvertAnonymousDescriptor; import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory; import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; import org.eclipse.jdt.internal.corext.dom.ASTNodes; import org.eclipse.jdt.internal.corext.dom.Bindings; import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder; import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel; import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroup; import org.eclipse.jdt.internal.corext.refactoring.Checks; import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil; import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; import org.eclipse.jdt.internal.corext.util.JdtFlags; import org.eclipse.jdt.internal.corext.util.Messages; import org.eclipse.jdt.ui.CodeGeneration; import org.eclipse.jdt.ui.JavaElementLabels; import org.eclipse.jdt.internal.ui.text.correction.ModifierCorrectionSubProcessor; import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; public class ConvertAnonymousToNestedRefactoring extends Refactoring { private static final String ATTRIBUTE_VISIBILITY= "visibility"; //$NON-NLS-1$ private static final String ATTRIBUTE_FINAL= "final"; //$NON-NLS-1$ private static final String ATTRIBUTE_STATIC= "static"; //$NON-NLS-1$ private static final String KEY_TYPE_NAME= "type_name"; //$NON-NLS-1$ private static final String KEY_PARAM_NAME_EXT= "param_name_ext"; //$NON-NLS-1$ private static final String KEY_PARAM_NAME_CONST= "param_name_const"; //$NON-NLS-1$ private static final String KEY_FIELD_NAME_EXT= "field_name_ext"; //$NON-NLS-1$ public static class TypeVariableFinder extends ASTVisitor { private final Map<String, ITypeBinding> fBindings= new HashMap<String, ITypeBinding>(); private final List<ITypeBinding> fFound= new ArrayList<ITypeBinding>(); @Override public final boolean visit(final SimpleName node) { Assert.isNotNull(node); final ITypeBinding binding= node.resolveTypeBinding(); if (binding != null && binding.isTypeVariable() && !fBindings.containsKey(binding.getKey())) { fBindings.put(binding.getKey(), binding); fFound.add(binding); } return true; } public final ITypeBinding[] getResult() { final ITypeBinding[] result= new ITypeBinding[fFound.size()]; fFound.toArray(result); return result; } } private int fSelectionStart; private int fSelectionLength; private ICompilationUnit fCu; private int fVisibility; /* see Modifier */ private boolean fDeclareFinal= true; private boolean fDeclareStatic; private String fClassName= ""; //$NON-NLS-1$ private CompilationUnit fCompilationUnitNode; private AnonymousClassDeclaration fAnonymousInnerClassNode; private Set<String> fClassNamesUsed; private boolean fSelfInitializing= false; private LinkedProposalModel fLinkedProposalModel; /** * Creates a new convert anonymous to nested refactoring. * * @param unit the compilation unit, or <code>null</code> if invoked by scripting * @param selectionStart start * @param selectionLength length */ public ConvertAnonymousToNestedRefactoring(ICompilationUnit unit, int selectionStart, int selectionLength) { Assert.isTrue(selectionStart >= 0); Assert.isTrue(selectionLength >= 0); Assert.isTrue(unit == null || unit.exists()); fSelectionStart= selectionStart; fSelectionLength= selectionLength; fCu= unit; fAnonymousInnerClassNode= null; fCompilationUnitNode= null; } public ConvertAnonymousToNestedRefactoring(AnonymousClassDeclaration declaration) { Assert.isTrue(declaration != null); ASTNode astRoot= declaration.getRoot(); Assert.isTrue(astRoot instanceof CompilationUnit); fCompilationUnitNode= (CompilationUnit) astRoot; IJavaElement javaElement= fCompilationUnitNode.getJavaElement(); Assert.isTrue(javaElement instanceof ICompilationUnit); fCu= (ICompilationUnit) javaElement; fSelectionStart= declaration.getStartPosition(); fSelectionLength= declaration.getLength(); } public ConvertAnonymousToNestedRefactoring(JavaRefactoringArguments arguments, RefactoringStatus status) { this(null, 0, 0); RefactoringStatus initializeStatus= initialize(arguments); status.merge(initializeStatus); } public void setLinkedProposalModel(LinkedProposalModel linkedProposalModel) { fLinkedProposalModel= linkedProposalModel; } public int[] getAvailableVisibilities() { if (isLocalInnerType()) { return new int[] { Modifier.NONE }; } else { return new int[] { Modifier.PUBLIC, Modifier.PROTECTED, Modifier.NONE, Modifier.PRIVATE }; } } public boolean isLocalInnerType() { return ASTNodes.getParent(ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class), ASTNode.ANONYMOUS_CLASS_DECLARATION) != null; } public int getVisibility() { return fVisibility; } public void setVisibility(int visibility) { Assert.isTrue(visibility == Modifier.PRIVATE || visibility == Modifier.NONE || visibility == Modifier.PROTECTED || visibility == Modifier.PUBLIC); fVisibility= visibility; } public void setClassName(String className) { Assert.isNotNull(className); fClassName= className; } public boolean canEnableSettingFinal() { return true; } public boolean getDeclareFinal() { return fDeclareFinal; } public boolean getDeclareStatic() { return fDeclareStatic; } public void setDeclareFinal(boolean declareFinal) { fDeclareFinal= declareFinal; } public void setDeclareStatic(boolean declareStatic) { fDeclareStatic= declareStatic; } @Override public String getName() { return RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name; } private boolean useThisForFieldAccess() { return StubUtility.useThisForFieldAccess(fCu.getJavaProject()); } private boolean doAddComments() { return StubUtility.doAddComments(fCu.getJavaProject()); } @Override public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { RefactoringStatus result= Checks.validateModifiesFiles( ResourceUtil.getFiles(new ICompilationUnit[]{fCu}), getValidationContext()); if (result.hasFatalError()) return result; initAST(pm); if (fAnonymousInnerClassNode == null) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_place_caret); if (!fSelfInitializing) initializeDefaults(); if (getSuperConstructorBinding() == null) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_compile_errors); if (getSuperTypeBinding().isLocal()) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_extends_local_class); return new RefactoringStatus(); } private void initializeDefaults() { fVisibility= isLocalInnerType() ? Modifier.NONE : Modifier.PRIVATE; fDeclareStatic = mustInnerClassBeStatic(); } private void initAST(IProgressMonitor pm) { if (fCompilationUnitNode == null) { fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, pm); } if (fAnonymousInnerClassNode == null) { fAnonymousInnerClassNode= getAnonymousInnerClass(NodeFinder.perform(fCompilationUnitNode, fSelectionStart, fSelectionLength)); } if (fAnonymousInnerClassNode != null) { final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class); if (declaration instanceof TypeDeclaration) { final AbstractTypeDeclaration[] nested= ((TypeDeclaration) declaration).getTypes(); fClassNamesUsed= new HashSet<String>(nested.length); for (int index= 0; index < nested.length; index++) fClassNamesUsed.add(nested[index].getName().getIdentifier()); } else fClassNamesUsed= Collections.emptySet(); } } private static AnonymousClassDeclaration getAnonymousInnerClass(ASTNode node) { if (node == null) return null; if (node instanceof AnonymousClassDeclaration) return (AnonymousClassDeclaration)node; if (node instanceof ClassInstanceCreation) { AnonymousClassDeclaration anon= ((ClassInstanceCreation)node).getAnonymousClassDeclaration(); if (anon != null) return anon; } node= ASTNodes.getNormalizedNode(node); if (node.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY) { AnonymousClassDeclaration anon= ((ClassInstanceCreation)node.getParent()).getAnonymousClassDeclaration(); if (anon != null) return anon; } return (AnonymousClassDeclaration)ASTNodes.getParent(node, AnonymousClassDeclaration.class); } public RefactoringStatus validateInput() { RefactoringStatus result= Checks.checkTypeName(fClassName, fCu); if (result.hasFatalError()) return result; if (fClassNamesUsed.contains(fClassName)) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_type_exists); IMethodBinding superConstructorBinding = getSuperConstructorBinding(); if (superConstructorBinding == null) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_compile_errors); if (fClassName.equals(superConstructorBinding.getDeclaringClass().getName())) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_another_name); if (classNameHidesEnclosingType()) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name_hides); return result; } private boolean accessesAnonymousFields() { List<IVariableBinding> anonymousInnerFieldTypes = getAllEnclosingAnonymousTypesField(); List<IBinding> accessedField = getAllAccessedFields(); final Iterator<IVariableBinding> it = anonymousInnerFieldTypes.iterator(); while(it.hasNext()) { final IVariableBinding variableBinding = it.next(); final Iterator<IBinding> it2 = accessedField.iterator(); while (it2.hasNext()) { IVariableBinding variableBinding2 = (IVariableBinding) it2.next(); if(Bindings.equals(variableBinding, variableBinding2)) { return true; } } } return false; } private List<IBinding> getAllAccessedFields() { final List<IBinding> accessedFields= new ArrayList<IBinding>(); ASTVisitor visitor= new ASTVisitor() { @Override public boolean visit(FieldAccess node) { final IVariableBinding binding= node.resolveFieldBinding(); if (binding != null && !binding.isEnumConstant()) accessedFields.add(binding); return super.visit(node); } @Override public boolean visit(QualifiedName node) { final IBinding binding= node.resolveBinding(); if (binding != null && binding instanceof IVariableBinding) { IVariableBinding variable= (IVariableBinding) binding; if (!variable.isEnumConstant() && variable.isField()) accessedFields.add(binding); } return super.visit(node); } @Override public boolean visit(SimpleName node) { final IBinding binding= node.resolveBinding(); if (binding != null && binding instanceof IVariableBinding) { IVariableBinding variable= (IVariableBinding) binding; if (!variable.isEnumConstant() && variable.isField()) accessedFields.add(binding); } return super.visit(node); } @Override public boolean visit(SuperFieldAccess node) { final IVariableBinding binding= node.resolveFieldBinding(); if (binding != null && !binding.isEnumConstant()) accessedFields.add(binding); return super.visit(node); } }; fAnonymousInnerClassNode.accept(visitor); return accessedFields; } private List<IVariableBinding> getAllEnclosingAnonymousTypesField() { final List<IVariableBinding> ans= new ArrayList<IVariableBinding>(); final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class); AnonymousClassDeclaration anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, ASTNode.ANONYMOUS_CLASS_DECLARATION); while (anonymous != null) { if (ASTNodes.isParent(anonymous, declaration)) { ITypeBinding binding= anonymous.resolveBinding(); if (binding != null) { ans.addAll(Arrays.asList(binding.getDeclaredFields())); } } else { break; } anonymous= (AnonymousClassDeclaration) ASTNodes.getParent(anonymous, ASTNode.ANONYMOUS_CLASS_DECLARATION); } return ans; } private boolean classNameHidesEnclosingType() { ITypeBinding type= ((AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class)).resolveBinding(); while (type != null) { if (fClassName.equals(type.getName())) return true; type= type.getDeclaringClass(); } return false; } /* * @see org.eclipse.jdt.internal.corext.refactoring.base.Refactoring#checkInput(org.eclipse.core.runtime.IProgressMonitor) */ @Override public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { try { RefactoringStatus status= validateInput(); if (accessesAnonymousFields()) status.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_anonymous_field_access)); return status; } finally { pm.done(); } } public CompilationUnitChange createCompilationUnitChange(IProgressMonitor pm) throws CoreException { final CompilationUnitRewrite rewrite= new CompilationUnitRewrite(fCu, fCompilationUnitNode); final ITypeBinding[] typeParameters= getTypeParameters(); addNestedClass(rewrite, typeParameters); modifyConstructorCall(rewrite, typeParameters); return rewrite.createChange(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_name, false, pm); } /* * @see org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring#createChange(org.eclipse.core.runtime.IProgressMonitor) */ @Override public Change createChange(IProgressMonitor pm) throws CoreException { final CompilationUnitChange result= createCompilationUnitChange(pm); result.setDescriptor(createRefactoringDescriptor()); return result; } private ITypeBinding[] getTypeParameters() { final List<ITypeBinding> parameters= new ArrayList<ITypeBinding>(4); final ClassInstanceCreation creation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent(); if (fDeclareStatic) { final TypeVariableFinder finder= new TypeVariableFinder(); creation.accept(finder); return finder.getResult(); } else { final MethodDeclaration declaration= getEnclosingMethodDeclaration(creation); if (declaration != null) { ITypeBinding binding= null; TypeParameter parameter= null; for (final Iterator<TypeParameter> iterator= declaration.typeParameters().iterator(); iterator.hasNext();) { parameter= iterator.next(); binding= parameter.resolveBinding(); if (binding != null) parameters.add(binding); } } } final TypeVariableFinder finder= new TypeVariableFinder(); creation.accept(finder); final ITypeBinding[] variables= finder.getResult(); final List<ITypeBinding> remove= new ArrayList<ITypeBinding>(4); boolean match= false; ITypeBinding binding= null; ITypeBinding variable= null; for (final Iterator<ITypeBinding> iterator= parameters.iterator(); iterator.hasNext();) { match= false; binding= iterator.next(); for (int index= 0; index < variables.length; index++) { variable= variables[index]; if (variable.equals(binding)) match= true; } if (!match) remove.add(binding); } parameters.removeAll(remove); final ITypeBinding[] result= new ITypeBinding[parameters.size()]; parameters.toArray(result); return result; } private MethodDeclaration getEnclosingMethodDeclaration(ASTNode node) { ASTNode parent= node.getParent(); if (parent != null) { if (parent instanceof AbstractTypeDeclaration) return null; else if (parent instanceof MethodDeclaration) return (MethodDeclaration) parent; return getEnclosingMethodDeclaration(parent); } return null; } private RefactoringChangeDescriptor createRefactoringDescriptor() { final ITypeBinding binding= fAnonymousInnerClassNode.resolveBinding(); final String[] labels= new String[] { BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED), BindingLabelProvider.getBindingLabel(binding.getDeclaringMethod(), JavaElementLabels.ALL_FULLY_QUALIFIED)}; final Map<String, String> arguments= new HashMap<String, String>(); final String projectName= fCu.getJavaProject().getElementName(); final int flags= RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; final String description= RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_descriptor_description_short; final String header= Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_descriptor_description, labels); final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(projectName, this, header); comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_original_pattern, BindingLabelProvider.getBindingLabel(binding, JavaElementLabels.ALL_FULLY_QUALIFIED))); comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_class_name_pattern, BasicElementLabels.getJavaElementName(fClassName))); String visibility= JdtFlags.getVisibilityString(fVisibility); if (visibility.length() == 0) visibility= RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_default_visibility; comment.addSetting(Messages.format(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_visibility_pattern, visibility)); if (fDeclareFinal && fDeclareStatic) comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_final_static); else if (fDeclareFinal) comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_final); else if (fDeclareStatic) comment.addSetting(RefactoringCoreMessages.ConvertAnonymousToNestedRefactoring_declare_static); arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(projectName, fCu)); arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME, fClassName); arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, new Integer(fSelectionStart).toString() + ' ' + new Integer(fSelectionLength).toString()); arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fDeclareFinal).toString()); arguments.put(ATTRIBUTE_STATIC, Boolean.valueOf(fDeclareStatic).toString()); arguments.put(ATTRIBUTE_VISIBILITY, new Integer(fVisibility).toString()); ConvertAnonymousDescriptor descriptor= RefactoringSignatureDescriptorFactory.createConvertAnonymousDescriptor(projectName, description, comment.asString(), arguments, flags); return new RefactoringChangeDescriptor(descriptor); } private void modifyConstructorCall(CompilationUnitRewrite rewrite, ITypeBinding[] parameters) { rewrite.getASTRewrite().replace(fAnonymousInnerClassNode.getParent(), createNewClassInstanceCreation(rewrite, parameters), null); } private ASTNode createNewClassInstanceCreation(CompilationUnitRewrite rewrite, ITypeBinding[] parameters) { AST ast= fAnonymousInnerClassNode.getAST(); ClassInstanceCreation newClassCreation= ast.newClassInstanceCreation(); newClassCreation.setAnonymousClassDeclaration(null); Type type= null; SimpleName newNameNode= ast.newSimpleName(fClassName); if (parameters.length > 0) { final ParameterizedType parameterized= ast.newParameterizedType(ast.newSimpleType(newNameNode)); for (int index= 0; index < parameters.length; index++) parameterized.typeArguments().add(ast.newSimpleType(ast.newSimpleName(parameters[index].getName()))); type= parameterized; } else type= ast.newSimpleType(newNameNode); newClassCreation.setType(type); copyArguments(rewrite, newClassCreation); addArgumentsForLocalsUsedInInnerClass(newClassCreation); addLinkedPosition(KEY_TYPE_NAME, newNameNode, rewrite.getASTRewrite(), true); return newClassCreation; } private void addArgumentsForLocalsUsedInInnerClass(ClassInstanceCreation newClassCreation) { IVariableBinding[] usedLocals= getUsedLocalVariables(); for (int i= 0; i < usedLocals.length; i++) { final AST ast= fAnonymousInnerClassNode.getAST(); final IVariableBinding binding= usedLocals[i]; Name name= null; if (binding.isEnumConstant()) name= ast.newQualifiedName(ast.newSimpleName(binding.getDeclaringClass().getName()), ast.newSimpleName(binding.getName())); else name= ast.newSimpleName(binding.getName()); newClassCreation.arguments().add(name); } } private void copyArguments(CompilationUnitRewrite rewrite, ClassInstanceCreation newClassCreation) { Iterator<Expression> iter= ((ClassInstanceCreation) fAnonymousInnerClassNode.getParent()).arguments().iterator(); if (!iter.hasNext()) return; IMethodBinding superConstructorBinding= getSuperConstructorBinding(); ITypeBinding[] parameterTypes= superConstructorBinding.getParameterTypes(); List<Expression> arguments= newClassCreation.arguments(); ASTRewrite astRewrite= rewrite.getASTRewrite(); int last= parameterTypes.length - 1; for (int i= 0; i < last; i++) { arguments.add((Expression) astRewrite.createCopyTarget(iter.next())); } if (superConstructorBinding.isVarargs()) { AST ast= astRewrite.getAST(); ArrayCreation arrayCreation= ast.newArrayCreation(); arrayCreation.setType((ArrayType) rewrite.getImportRewrite().addImport(parameterTypes[last], ast)); ArrayInitializer initializer= ast.newArrayInitializer(); arrayCreation.setInitializer(initializer); arguments.add(arrayCreation); arguments= initializer.expressions(); } while (iter.hasNext()) { arguments.add((Expression) astRewrite.createCopyTarget(iter.next())); } } private void addNestedClass(CompilationUnitRewrite rewrite, ITypeBinding[] typeParameters) throws CoreException { final AbstractTypeDeclaration declarations= (AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class); int index= findIndexOfFistNestedClass(declarations.bodyDeclarations()); if (index == -1) index= 0; rewrite.getASTRewrite().getListRewrite(declarations, declarations.getBodyDeclarationsProperty()).insertAt(createNewNestedClass(rewrite, typeParameters), index, null); } private static int findIndexOfFistNestedClass(List<BodyDeclaration> list) { for (int i= 0, n= list.size(); i < n; i++) { BodyDeclaration each= list.get(i); if (isNestedType(each)) return i; } return -1; } private static boolean isNestedType(BodyDeclaration each) { if (!(each instanceof AbstractTypeDeclaration)) return false; return (each.getParent() instanceof AbstractTypeDeclaration); } private AbstractTypeDeclaration createNewNestedClass(CompilationUnitRewrite rewrite, ITypeBinding[] typeParameters) throws CoreException { final AST ast= fAnonymousInnerClassNode.getAST(); final TypeDeclaration newDeclaration= ast.newTypeDeclaration(); newDeclaration.setInterface(false); newDeclaration.setJavadoc(null); newDeclaration.modifiers().addAll(ASTNodeFactory.newModifiers(ast, createModifiersForNestedClass())); newDeclaration.setName(ast.newSimpleName(fClassName)); TypeParameter parameter= null; for (int index= 0; index < typeParameters.length; index++) { parameter= ast.newTypeParameter(); parameter.setName(ast.newSimpleName(typeParameters[index].getName())); newDeclaration.typeParameters().add(parameter); } setSuperType(newDeclaration); IJavaProject project= fCu.getJavaProject(); IVariableBinding[] bindings= getUsedLocalVariables(); ArrayList<String> fieldNames= new ArrayList<String>(); for (int i= 0; i < bindings.length; i++) { String name= StubUtility.getBaseName(bindings[i], project); String[] fieldNameProposals= StubUtility.getVariableNameSuggestions(NamingConventions.VK_INSTANCE_FIELD, project, name, 0, fieldNames, true); fieldNames.add(fieldNameProposals[0]); if (fLinkedProposalModel != null) { LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_FIELD_NAME_EXT + i, true); for (int k= 0; k < fieldNameProposals.length; k++) { positionGroup.addProposal(fieldNameProposals[k], null, fieldNameProposals.length - k); } } } String[] allFieldNames= fieldNames.toArray(new String[fieldNames.size()]); List<BodyDeclaration> newBodyDeclarations= newDeclaration.bodyDeclarations(); createFieldsForAccessedLocals(rewrite, bindings, allFieldNames, newBodyDeclarations); MethodDeclaration newConstructorDecl= createNewConstructor(rewrite, bindings, allFieldNames); if (newConstructorDecl != null) { newBodyDeclarations.add(newConstructorDecl); } updateAndMoveBodyDeclarations(rewrite, bindings, allFieldNames, newBodyDeclarations, newConstructorDecl); if (doAddComments()) { String[] parameterNames= new String[typeParameters.length]; for (int index= 0; index < parameterNames.length; index++) { parameterNames[index]= typeParameters[index].getName(); } String string= CodeGeneration.getTypeComment(rewrite.getCu(), fClassName, parameterNames, StubUtility.getLineDelimiterUsed(fCu)); if (string != null) { Javadoc javadoc= (Javadoc) rewrite.getASTRewrite().createStringPlaceholder(string, ASTNode.JAVADOC); newDeclaration.setJavadoc(javadoc); } } if (fLinkedProposalModel != null) { addLinkedPosition(KEY_TYPE_NAME, newDeclaration.getName(), rewrite.getASTRewrite(), false); ModifierCorrectionSubProcessor.installLinkedVisibilityProposals(fLinkedProposalModel, rewrite.getASTRewrite(), newDeclaration.modifiers(), false); } return newDeclaration; } private void updateAndMoveBodyDeclarations(CompilationUnitRewrite rewriter, IVariableBinding[] bindings, String[] fieldNames, List<BodyDeclaration> newBodyDeclarations, MethodDeclaration newConstructorDecl) { final ASTRewrite astRewrite= rewriter.getASTRewrite(); final AST ast= astRewrite.getAST(); final boolean useThisAccess= useThisForFieldAccess(); int fieldInsertIndex= newConstructorDecl != null ? newBodyDeclarations.lastIndexOf(newConstructorDecl) : newBodyDeclarations.size(); for (Iterator<BodyDeclaration> iterator= fAnonymousInnerClassNode.bodyDeclarations().iterator(); iterator.hasNext();) { BodyDeclaration body= iterator.next(); for (int i= 0; i < bindings.length; i++) { SimpleName[] names= LinkedNodeFinder.findByBinding(body, bindings[i]); String fieldName= fieldNames[i]; for (int k= 0; k < names.length; k++) { SimpleName newNode= ast.newSimpleName(fieldName); if (useThisAccess) { FieldAccess access= ast.newFieldAccess(); access.setExpression(ast.newThisExpression()); access.setName(newNode); astRewrite.replace(names[k], access, null); } else { astRewrite.replace(names[k], newNode, null); } addLinkedPosition(KEY_FIELD_NAME_EXT + i, newNode, astRewrite, false); } } if (body instanceof Initializer || body instanceof FieldDeclaration) { newBodyDeclarations.add(fieldInsertIndex++, (BodyDeclaration) astRewrite.createMoveTarget(body)); } else { newBodyDeclarations.add((BodyDeclaration) astRewrite.createMoveTarget(body)); } } if (newConstructorDecl != null) { // move initialization of existing fields to constructor if an outer is referenced List<Statement> bodyStatements= newConstructorDecl.getBody().statements(); List<VariableDeclarationFragment> fieldsToInitializeInConstructor= getFieldsToInitializeInConstructor(); for (Iterator<VariableDeclarationFragment> iter= fieldsToInitializeInConstructor.iterator(); iter.hasNext();) { VariableDeclarationFragment fragment= iter.next(); Expression initializer= fragment.getInitializer(); Expression replacement= (Expression) astRewrite.get(fragment, VariableDeclarationFragment.INITIALIZER_PROPERTY); if (replacement == initializer) { replacement= (Expression) astRewrite.createMoveTarget(initializer); } astRewrite.remove(initializer, null); SimpleName fieldNameNode= ast.newSimpleName(fragment.getName().getIdentifier()); bodyStatements.add(newFieldAssignment(ast, fieldNameNode, replacement, useThisAccess)); } } } private void createFieldsForAccessedLocals(CompilationUnitRewrite rewrite, IVariableBinding[] varBindings, String[] fieldNames, List<BodyDeclaration> newBodyDeclarations) throws CoreException { final ImportRewrite importRewrite= rewrite.getImportRewrite(); final ASTRewrite astRewrite= rewrite.getASTRewrite(); final AST ast= astRewrite.getAST(); for (int i= 0; i < varBindings.length; i++) { VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment(); fragment.setExtraDimensions(0); fragment.setInitializer(null); fragment.setName(ast.newSimpleName(fieldNames[i])); FieldDeclaration field= ast.newFieldDeclaration(fragment); ITypeBinding varType= varBindings[i].getType(); field.setType(importRewrite.addImport(varType, ast)); field.modifiers().addAll(ASTNodeFactory.newModifiers(ast, Modifier.PRIVATE | Modifier.FINAL)); if (doAddComments()) { String string= CodeGeneration.getFieldComment(rewrite.getCu(), varType.getName(), fieldNames[i], StubUtility.getLineDelimiterUsed(fCu)); if (string != null) { Javadoc javadoc= (Javadoc) astRewrite.createStringPlaceholder(string, ASTNode.JAVADOC); field.setJavadoc(javadoc); } } newBodyDeclarations.add(field); addLinkedPosition(KEY_FIELD_NAME_EXT + i, fragment.getName(), astRewrite, false); } } private void addLinkedPosition(String key, ASTNode nodeToTrack, ASTRewrite rewrite, boolean isFirst) { if (fLinkedProposalModel != null) { fLinkedProposalModel.getPositionGroup(key, true).addPosition(rewrite.track(nodeToTrack), isFirst); } } private IVariableBinding[] getUsedLocalVariables() { final Set<IBinding> result= new HashSet<IBinding>(0); collectRefrencedVariables(fAnonymousInnerClassNode, result); ArrayList<IVariableBinding> usedLocals= new ArrayList<IVariableBinding>(); for (Iterator<IBinding> iterator= result.iterator(); iterator.hasNext();) { IVariableBinding next= (IVariableBinding) iterator.next(); if (isBindingToTemp(next)) { usedLocals.add(next); } } return usedLocals.toArray(new IVariableBinding[usedLocals.size()]); } private void collectRefrencedVariables(ASTNode root, final Set<IBinding> result) { root.accept(new ASTVisitor() { @Override public boolean visit(SimpleName node) { IBinding binding= node.resolveBinding(); if (binding instanceof IVariableBinding) result.add(binding); return true; } }); } private boolean isBindingToTemp(IVariableBinding variable) { if (variable.isField()) return false; if (!Modifier.isFinal(variable.getModifiers())) return false; ASTNode declaringNode= fCompilationUnitNode.findDeclaringNode(variable); if (declaringNode == null) return false; if (ASTNodes.isParent(declaringNode, fAnonymousInnerClassNode)) return false; return true; } private MethodDeclaration createNewConstructor(CompilationUnitRewrite rewrite, IVariableBinding[] bindings, String[] fieldNames) throws JavaModelException { ClassInstanceCreation instanceCreation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent(); if (instanceCreation.arguments().isEmpty() && bindings.length == 0) return null; IJavaProject project= fCu.getJavaProject(); AST ast= rewrite.getAST(); ImportRewrite importRewrite= rewrite.getImportRewrite(); ASTRewrite astRewrite= rewrite.getASTRewrite(); MethodDeclaration newConstructor= ast.newMethodDeclaration(); newConstructor.setConstructor(true); newConstructor.setExtraDimensions(0); newConstructor.setJavadoc(null); newConstructor.modifiers().addAll(ASTNodeFactory.newModifiers(ast, fVisibility)); newConstructor.setName(ast.newSimpleName(fClassName)); addLinkedPosition(KEY_TYPE_NAME, newConstructor.getName(), astRewrite, false); newConstructor.setBody(ast.newBlock()); List<Statement> newStatements= newConstructor.getBody().statements(); List<SingleVariableDeclaration> newParameters= newConstructor.parameters(); List<String> newParameterNames= new ArrayList<String>(); // add parameters for elements passed with the instance creation if (!instanceCreation.arguments().isEmpty()) { IMethodBinding constructorBinding= getSuperConstructorBinding(); if (constructorBinding != null) { SuperConstructorInvocation superConstructorInvocation= ast.newSuperConstructorInvocation(); ITypeBinding[] parameterTypes= constructorBinding.getParameterTypes(); String[][] parameterNames= StubUtility.suggestArgumentNamesWithProposals(project, constructorBinding); for (int i= 0; i < parameterNames.length; i++) { String[] nameProposals= parameterNames[i]; String paramName= nameProposals[0]; SingleVariableDeclaration param= newParameterDeclaration(ast, importRewrite, paramName, parameterTypes[i]); newParameters.add(param); newParameterNames.add(paramName); SimpleName newSIArgument= ast.newSimpleName(paramName); superConstructorInvocation.arguments().add(newSIArgument); if (fLinkedProposalModel != null) { LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_PARAM_NAME_CONST+ String.valueOf(i), true); positionGroup.addPosition(astRewrite.track(param.getName()), false); positionGroup.addPosition(astRewrite.track(newSIArgument), false); for (int k= 0; k < nameProposals.length; k++) { positionGroup.addProposal(nameProposals[k], null, nameProposals.length - k); } } } newStatements.add(superConstructorInvocation); } } // add parameters for all outer variables used boolean useThisAccess= useThisForFieldAccess(); for (int i= 0; i < bindings.length; i++) { String baseName= StubUtility.getBaseName(bindings[i], project); String[] paramNameProposals= StubUtility.getVariableNameSuggestions(NamingConventions.VK_PARAMETER, project, baseName, 0, newParameterNames, true); String paramName= paramNameProposals[0]; SingleVariableDeclaration param= newParameterDeclaration(ast, importRewrite, paramName, bindings[i].getType()); newParameters.add(param); newParameterNames.add(paramName); String fieldName= fieldNames[i]; SimpleName fieldNameNode= ast.newSimpleName(fieldName); SimpleName paramNameNode= ast.newSimpleName(paramName); newStatements.add(newFieldAssignment(ast, fieldNameNode, paramNameNode, useThisAccess || newParameterNames.contains(fieldName))); if (fLinkedProposalModel != null) { LinkedProposalPositionGroup positionGroup= fLinkedProposalModel.getPositionGroup(KEY_PARAM_NAME_EXT+ String.valueOf(i), true); positionGroup.addPosition(astRewrite.track(param.getName()), false); positionGroup.addPosition(astRewrite.track(paramNameNode), false); for (int k= 0; k < paramNameProposals.length; k++) { positionGroup.addProposal(paramNameProposals[k], null, paramNameProposals.length - k); } fLinkedProposalModel.getPositionGroup(KEY_FIELD_NAME_EXT + i, true).addPosition(astRewrite.track(fieldNameNode), false); } } addExceptionsToNewConstructor(newConstructor); if (doAddComments()) { try { String[] allParamNames= newParameterNames.toArray(new String[newParameterNames.size()]); String string= CodeGeneration.getMethodComment(fCu, fClassName, fClassName, allParamNames, new String[0], null, new String[0], null, StubUtility.getLineDelimiterUsed(fCu)); if (string != null) { Javadoc javadoc= (Javadoc) astRewrite.createStringPlaceholder(string, ASTNode.JAVADOC); newConstructor.setJavadoc(javadoc); } } catch (CoreException exception) { throw new JavaModelException(exception); } } return newConstructor; } private Statement newFieldAssignment(AST ast, SimpleName fieldNameNode, Expression initializer, boolean useThisAccess) { Assignment assignment= ast.newAssignment(); if (useThisAccess) { FieldAccess access= ast.newFieldAccess(); access.setExpression(ast.newThisExpression()); access.setName(fieldNameNode); assignment.setLeftHandSide(access); } else { assignment.setLeftHandSide(fieldNameNode); } assignment.setOperator(Assignment.Operator.ASSIGN); assignment.setRightHandSide(initializer); return ast.newExpressionStatement(assignment); } // live List of VariableDeclarationFragments private List<VariableDeclarationFragment> getFieldsToInitializeInConstructor() { List<VariableDeclarationFragment> result= new ArrayList<VariableDeclarationFragment>(0); for (Iterator<BodyDeclaration> iter= fAnonymousInnerClassNode.bodyDeclarations().iterator(); iter.hasNext(); ) { Object element= iter.next(); if (element instanceof FieldDeclaration) { List<VariableDeclarationFragment> fragments= ((FieldDeclaration) element).fragments(); for (Iterator<VariableDeclarationFragment> fragmentIter= fragments.iterator(); fragmentIter.hasNext(); ) { VariableDeclarationFragment fragment= fragmentIter.next(); if (isToBeInitializerInConstructor(fragment, result)) result.add(fragment); } } } return result; } private boolean isToBeInitializerInConstructor(VariableDeclarationFragment fragment, List<VariableDeclarationFragment> fieldsToInitialize) { return fragment.getInitializer() != null && areLocalsUsedIn(fragment.getInitializer(), fieldsToInitialize); } private boolean areLocalsUsedIn(Expression fieldInitializer, List<VariableDeclarationFragment> fieldsToInitialize) { Set<IBinding> localsUsed= new HashSet<IBinding>(0); collectRefrencedVariables(fieldInitializer, localsUsed); ITypeBinding anonType= fAnonymousInnerClassNode.resolveBinding(); for (Iterator<IBinding> iterator= localsUsed.iterator(); iterator.hasNext();) { IVariableBinding curr= (IVariableBinding) iterator.next(); if (isBindingToTemp(curr)) { // reference a local from outside return true; } else if (curr.isField() && (curr.getDeclaringClass() == anonType) && fieldsToInitialize.contains(fCompilationUnitNode.findDeclaringNode(curr))) { return true; // references a field that references a local from outside } } return false; } private IMethodBinding getSuperConstructorBinding() { //workaround for missing java core functionality - finding a // super constructor for an anonymous class creation IMethodBinding anonConstr= ((ClassInstanceCreation) fAnonymousInnerClassNode.getParent()).resolveConstructorBinding(); if (anonConstr == null) return null; ITypeBinding superClass= anonConstr.getDeclaringClass().getSuperclass(); IMethodBinding[] superMethods= superClass.getDeclaredMethods(); for (int i= 0; i < superMethods.length; i++) { IMethodBinding superMethod= superMethods[i]; if (superMethod.isConstructor() && parameterTypesMatch(superMethod, anonConstr)) return superMethod; } Assert.isTrue(false);//there's no way - it must be there return null; } private static boolean parameterTypesMatch(IMethodBinding m1, IMethodBinding m2) { ITypeBinding[] m1Params= m1.getParameterTypes(); ITypeBinding[] m2Params= m2.getParameterTypes(); if (m1Params.length != m2Params.length) return false; for (int i= 0; i < m2Params.length; i++) { if (!m1Params[i].equals(m2Params[i])) return false; } return true; } private void addExceptionsToNewConstructor(MethodDeclaration newConstructor) { IMethodBinding constructorBinding= getSuperConstructorBinding(); if (constructorBinding == null) return; ITypeBinding[] exceptions= constructorBinding.getExceptionTypes(); for (int i= 0; i < exceptions.length; i++) { Name exceptionTypeName= fAnonymousInnerClassNode.getAST().newName(Bindings.getNameComponents(exceptions[i])); newConstructor.thrownExceptions().add(exceptionTypeName); } } private SingleVariableDeclaration newParameterDeclaration(AST ast, ImportRewrite importRewrite, String paramName, ITypeBinding paramType) { SingleVariableDeclaration param= ast.newSingleVariableDeclaration(); param.setExtraDimensions(0); param.setInitializer(null); param.setType(importRewrite.addImport(paramType, ast)); param.setName(ast.newSimpleName(paramName)); return param; } private void setSuperType(TypeDeclaration declaration) { ClassInstanceCreation classInstanceCreation= (ClassInstanceCreation) fAnonymousInnerClassNode.getParent(); ITypeBinding binding= classInstanceCreation.resolveTypeBinding(); if (binding == null) return; Type newType= (Type) ASTNode.copySubtree(fAnonymousInnerClassNode.getAST(), classInstanceCreation.getType()); if (binding.getSuperclass().getQualifiedName().equals("java.lang.Object")) { //$NON-NLS-1$ Assert.isTrue(binding.getInterfaces().length <= 1); if (binding.getInterfaces().length == 0) return; declaration.superInterfaceTypes().add(0, newType); } else { declaration.setSuperclassType(newType); } } private ITypeBinding getSuperTypeBinding() { ITypeBinding types= fAnonymousInnerClassNode.resolveBinding(); ITypeBinding[] interfaces= types.getInterfaces(); if (interfaces.length > 0) return interfaces[0]; else return types.getSuperclass(); } private int createModifiersForNestedClass() { int flags= fVisibility; if (fDeclareFinal) flags|= Modifier.FINAL; if (mustInnerClassBeStatic() || fDeclareStatic) flags|= Modifier.STATIC; return flags; } public boolean mustInnerClassBeStatic() { ITypeBinding typeBinding = ((AbstractTypeDeclaration) ASTNodes.getParent(fAnonymousInnerClassNode, AbstractTypeDeclaration.class)).resolveBinding(); ASTNode current = fAnonymousInnerClassNode.getParent(); boolean ans = false; while(current != null) { switch(current.getNodeType()) { case ASTNode.ANONYMOUS_CLASS_DECLARATION: { AnonymousClassDeclaration enclosingAnonymousClassDeclaration= (AnonymousClassDeclaration)current; ITypeBinding binding= enclosingAnonymousClassDeclaration.resolveBinding(); if (binding != null && Bindings.isSuperType(typeBinding, binding.getSuperclass())) { return false; } break; } case ASTNode.FIELD_DECLARATION: { FieldDeclaration enclosingFieldDeclaration= (FieldDeclaration)current; if (Modifier.isStatic(enclosingFieldDeclaration.getModifiers())) { ans = true; } break; } case ASTNode.METHOD_DECLARATION: { MethodDeclaration enclosingMethodDeclaration = (MethodDeclaration)current; if (Modifier.isStatic(enclosingMethodDeclaration.getModifiers())) { ans = true; } break; } case ASTNode.TYPE_DECLARATION: { return ans; } } current = current.getParent(); } return ans; } private RefactoringStatus initialize(JavaRefactoringArguments arguments) { fSelfInitializing= true; final String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT); if (handle != null) { final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false); if (element == null || !element.exists() || element.getElementType() != IJavaElement.COMPILATION_UNIT) return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.CONVERT_ANONYMOUS); else { fCu= (ICompilationUnit) element; } } else return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT)); final String name= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME); if (name != null && !"".equals(name)) //$NON-NLS-1$ fClassName= name; else return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME)); final String visibility= arguments.getAttribute(ATTRIBUTE_VISIBILITY); if (visibility != null && !"".equals(visibility)) {//$NON-NLS-1$ int flag= 0; try { flag= Integer.parseInt(visibility); } catch (NumberFormatException exception) { return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_VISIBILITY)); } fVisibility= flag; } final String selection= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION); if (selection != null) { int offset= -1; int length= -1; final StringTokenizer tokenizer= new StringTokenizer(selection); if (tokenizer.hasMoreTokens()) offset= Integer.valueOf(tokenizer.nextToken()).intValue(); if (tokenizer.hasMoreTokens()) length= Integer.valueOf(tokenizer.nextToken()).intValue(); if (offset >= 0 && length >= 0) { fSelectionStart= offset; fSelectionLength= length; } else return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION})); } else return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION)); final String declareStatic= arguments.getAttribute(ATTRIBUTE_STATIC); if (declareStatic != null) { fDeclareStatic= Boolean.valueOf(declareStatic).booleanValue(); } else return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_STATIC)); final String declareFinal= arguments.getAttribute(ATTRIBUTE_FINAL); if (declareFinal != null) { fDeclareFinal= Boolean.valueOf(declareStatic).booleanValue(); } else return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL)); return new RefactoringStatus(); } }